#!/usr/local/u-mail/app/engine/bin/python
# coding:utf-8

"""
wget http://update.comingchina.com:8080/testing/private/7/x86_64/umail_config-5.5.21-8.alpha.el7.x86_64.rpm
wget http://update.comingchina.com:8080/testing/private/7/x86_64/umail_app-2.3.18-1.alpha.el7.x86_64.rpm
yum install umail_config-5.5.21-8.alpha.el7.x86_64.rpm
yum install umail_app-2.3.18-1.alpha.el7.x86_64.rpm
"""
# import asyncore
from gevent import monkey;monkey.patch_all()
import socket
from gsmtpd import SMTPServer
from dns.resolver import Resolver
import logging


logger = logging.getLogger('smtpProxy')
logger.setLevel(logging.INFO)
#handler = logging.handlers.SysLogHandler(address='/dev/log', facility="mail")
handler = logging.StreamHandler()
formatter = logging.Formatter("%(asctime)s %(levelname)s %(message)s","%Y%m%d %H:%M:%S")
handler.setFormatter(formatter)
logger.addHandler(handler)


def parse_mx_answer(domain):
    answer = Resolver().query(domain, "MX")
    hostmaps = []
    srv_list = []
    for item in answer.rrset:
        address = item.exchange.to_text()
        address = address[:-1]
        hostmaps.append((item.preference, address))

    for item in sorted(hostmaps):
        srv_list.append(item[1])

    return srv_list


class PureProxy(SMTPServer):
    def process_message(self, peer, mailfrom, rcpttos, data):
        # lines = data.split('\n')
        # # Look for the last header
        # i = 0
        # for line in lines:
        #     if not line:
        #         break
        #     i += 1
        # lines.insert(i, 'X-Peer: %s' % peer[0])
        # data = NEWLINE.join(lines)
        # *******************************************************
        logger.info('Receiving message from: (%s:%s)' %peer)
        logger.info('Message addressed from: %s' % mailfrom)
        logger.info('Message addressed to  : %s' % rcpttos)
        logger.info('Message length        : %s' % len(data))
        # print data

        if "@josephrobinettebiden.top" not in mailfrom:
            logger.error("[ERROR] mailfrom:%s, no proxy smtp" % mailfrom)
            logger.error("*************NOTIFY*************")
            return

        for rcptto in rcpttos:
            # print rcptto
            if "@" not in rcptto:
                logger.error("error rcptto:%s"%rcptto)
                logger.error("*************NOTIFY*************")
                continue
            if len(rcptto.split("@")) != 2:
                logger.error("error rcptto:%s" % rcptto)
                continue
            domain = rcptto.split("@")[1]
            if "gmail.com" in domain:
                logger.error("gmail.com in domain")
                return
            if "qg.com" in domain:
                logger.error("qg.com in domain")
                return
            # print domain
            try:
                MXs = parse_mx_answer(domain)
            except:
                MXs = []
            if len(MXs)>3:
                MXs = MXs[:3]
            logger.info("domain:(%s)--->MXs:[%s]" % (domain, ",".join(MXs)))
            for MX in MXs:
                if 'iphmx.com' in MX:
                    logger.error("iphmx.com in MX")
                    return
                if 'gmail.com'in MX:
                    logger.error("gmail.com in MX")
                    return
                self._remoteaddr = (MX, 25)
                # *******************************************************
                refused = self._deliver(mailfrom, rcpttos, data)
                if not refused:
                    logger.info('Message addressed to %s success' % rcptto)
                    return
                logger.error("***********we got some refusals***********")
                logger.error(refused)
                logger.error("***********we got some refusals***********")

    def _deliver(self, mailfrom, rcpttos, data):
        import smtplib
        refused = {}
        try:
            s = smtplib.SMTP()
            s.connect(self._remoteaddr[0], self._remoteaddr[1])
            logger.info("(%s:%s)"%(self._remoteaddr[0], self._remoteaddr[1]))
            # s.set_debuglevel(1)
            try:
                refused = s.sendmail(mailfrom, rcpttos, data)
            finally:
                s.quit()
        except smtplib.SMTPRecipientsRefused, e:
            logger.error('got SMTPRecipientsRefused <%s>--><%s>'%(mailfrom, rcpttos))
            refused = e.recipients
        except (socket.error, smtplib.SMTPException), e:
            logger.error('got %s'%(e.__class__))
            # print 'got', e.__class__
            # All recipients were refused.  If the exception had an associated
            # error code, use it.  Otherwise,fake it with a non-triggering
            # exception code.
            errcode = getattr(e, 'smtp_code', -1)
            errmsg = getattr(e, 'smtp_error', 'ignore')
            for r in rcpttos:
                refused[r] = (errcode, errmsg)
        return refused


server = PureProxy(('0.0.0.0', 25))
server.serve_forever()